﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Hopscotch.Domain.Finance;
using Hopscotch.Presentation.Common;
using Hopscotch.Presentation.Common.Constants;
using Hopscotch.Presentation.Controls.Core;
using Hopscotch.Presentation.Controls.DataProviders;
using Moq;
using NUnit.Framework;

namespace Hopscotch.Presentation.Controls.Test
{
    [TestFixture, RequiresSTA]
    public class InstrumentControlTest
    {
        private InstrumentControl instrumentControl;
        private Mock<IInstrumentDataProvider> InstrumentDataProviderMock;
        private List<Instrument> instrumentList;

        [SetUp]
        public void Setup()
        {
            instrumentControl = new InstrumentControl();
            InstrumentDataProviderMock = new Mock<IInstrumentDataProvider>();

            instrumentList = new List<Instrument>()
			{
				new EquityInstrument() { Id = 1, Symbol = "ABC" },
				new EquityInstrument() { Id = 2, Symbol = "DEF" },
				new EquityInstrument() { Id = 3, Symbol = "XYZ" }
			};

            InstrumentDataProviderMock.Setup(x => x.SearchAsync(It.IsAny<string>()))
                .Returns((string s) => Task.FromResult<ICollection<Instrument>>(instrumentList.Where(p => p.Symbol == s).ToList()));

            InstrumentDataProviderMock.Setup(x => x.GetInstrument(It.IsAny<int>()))
                .Returns((int id) => Task.FromResult<Instrument>(instrumentList.FirstOrDefault(p => p.Id == id)));
        }

        [Test]
        public void TestControlHasErrorIfDataProviderNotSet()
        {
            instrumentControl.HasErrors.Should().BeTrue();
            var errors = instrumentControl.GetErrors(string.Empty);
            errors.Should().NotBeEmpty();
            errors.Should().HaveCount(1);
            foreach (DataErrorInfo error in errors)
            {
                error.ErrorType.Should().Be(ErrorType.Error);
                error.Description.Should().Be(ErrorMessages.DataProviderNotSetErrorMsg);
            }
        }

        [Test]
        public void TestSettingDataProviderRaisesErrorsChanged()
        {
            instrumentControl.HasErrors.Should().BeTrue();
            bool called = false;

            instrumentControl.ErrorsChanged += (s, e) => { called = true; };

            instrumentControl.DataProvider = InstrumentDataProviderMock.Object;
            instrumentControl.HasErrors.Should().BeFalse();

            called.Should().BeTrue("ErrorsChanged not raised");
        }

        [Test]
        public void TestSettingInstrumentSetsInstrumentId()
        {
            instrumentControl.DataProvider = InstrumentDataProviderMock.Object;

            instrumentControl.Instrument.Should().BeNull();
            instrumentControl.InstrumentId.Should().NotHaveValue();

            var instrument = instrumentList.FirstOrDefault(p => p.Id == 2);
            instrumentControl.Instrument = instrument;
            instrumentControl.InstrumentId.Should().Be(instrument.Id);
        }

        [Test]
        public void TestSettingInstrumentIdSetsInstrument()
        {
            instrumentControl.DataProvider = InstrumentDataProviderMock.Object;

            instrumentControl.Instrument.Should().BeNull();
            instrumentControl.InstrumentId.Should().NotHaveValue();

            var instrument = instrumentList.FirstOrDefault(p => p.Id == 2);
            instrumentControl.InstrumentId = instrument.Id; ;
            instrumentControl.Instrument.Id.Should().Be(instrument.Id);
        }
    }
}
